import React, { useEffect, useState, useRef, useCallback } from 'react';
import ReactDOM from 'react-dom';
import { debounce } from 'lodash';

// 每次组件重新渲染，都会执行一遍所有的hooks，
// 这样debounce高阶函数里面的timer就不能起到缓存的作用（每次重渲染都被置空）。
// timer不可靠，debounce的核心就被破坏了。

// function useDebounce(fn, time) {
//     console.log('debounce')
//     return debounce(fn, time);
// }

// hooks debounce
function useDebounce(fn, delay, dep = []) {
  const { current } = useRef({
    fn,
    timer: null,
  });

  useEffect(() => {
    current.fn = fn;
  }, [fn]);

  return useCallback(function f(...args) {
    if (current.timer) {
      clearTimeout(current.timer);
    }

    current.timer = setTimeout(() => {
      current.fn.call(this, ...args);
    }, delay);
  }, dep);
}

// hooks throttle
function useThrottle(fn, delay, dep = []) {
  const { current } = useRef({
    fn,
    timer: null,
  });

  useEffect(() => {
    current.fn = fn;
  }, [fn]);

  return useCallback(function f(...args) {
    if (!current.timer) {
      current.timer = setTimeout(() => {
        delete current.timer;
      }, delay);
      current.fn.call(this, ...args);
    }
  }, dep);
}

function App() {
  const [counter1, setCounter1] = useState(0);
  const [counter2, setCounter2] = useState(0);

  const handleClick = useDebounce(function () {
    console.count('click1');
    setCounter1(counter1 + 1);
  }, 500);

  useEffect(function () {
    const t = setInterval(() => {
      setCounter2((x) => x + 1);
    }, 500);

    return clearInterval.bind(undefined, t);
  }, []);

  return (
    <div style={{ padding: 30 }}>
      <button onClick={handleClick}>click</button>
      <div>{counter1}</div>
      <div>{counter2}</div>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
